/*
* Mesh.java
* Copyright (C) 2003
*
* $Id: Mesh.java,v 1.10 2005/05/08 00:42:22 cawe Exp $
*/
/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
using System;
using Defines = Suake2.UI.Defines;
using VID = Suake2.UI.client.VID;
using entity_t = Suake2.UI.client.entity_t;
using qfiles = Suake2.UI.qcommon.qfiles;
using image_t = Suake2.UI.render.image_t;
using Math3D = Suake2.UI.util.Math3D;
//UPGRADE_TODO: The type 'java.nio.FloatBuffer' could not be found. If it was not included in the conversion, there may be compiler issues. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1262'"
using FloatBuffer = java.nio.FloatBuffer;
using GL = net.java.games.jogl.GL;
using BufferUtils = net.java.games.jogl.util.BufferUtils;
namespace Suake2.UI.render.jogl
{
	
	/// <summary> Mesh
	/// 
	/// </summary>
	/// <author>  cwei
	/// </author>
	public abstract class Mesh:Light
	{
		public Mesh()
		{
			InitBlock();
		}
		private void  InitBlock()
		{
			for (int i = 0; i < qfiles.MAX_VERTS; i++)
			{
				s_lerped[i] = new float[4];
			}
			s_lerped = new float[qfiles.MAX_VERTS][];
			shadedots = r_avertexnormal_dots[0];
			colorArrayBuf = BufferUtils.newFloatBuffer(qfiles.MAX_VERTS * 4);
			vertexArrayBuf = BufferUtils.newFloatBuffer(qfiles.MAX_VERTS * 3);
		}
		
		// g_mesh.c: triangle model functions
		
		/*
		* =============================================================
		* 
		* ALIAS MODELS
		* 
		* =============================================================
		*/
		
		internal const int NUMVERTEXNORMALS = 162;
		
		internal float[][] r_avertexnormals = Suake2.UI.render.jogl.Anorms_Fields.VERTEXNORMALS;
		
		//UPGRADE_NOTE: The initialization of  's_lerped' was moved to method 'InitBlock'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal float[][] s_lerped;
		
		internal float[] shadevector = new float[]{0, 0, 0};
		
		internal float[] shadelight = new float[]{0, 0, 0};
		
		// precalculated dot products for quantized angles
		internal const int SHADEDOT_QUANT = 16;
		
		internal float[][] r_avertexnormal_dots = Suake2.UI.render.jogl.Anorms_Fields.VERTEXNORMAL_DOTS;
		
		//UPGRADE_NOTE: The initialization of  'shadedots' was moved to method 'InitBlock'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal float[] shadedots;
		
		internal virtual void  GL_LerpVerts(int nverts, int[] ov, int[] v, float[][] lerp, float[] move, float[] frontv, float[] backv)
		{
			int i;
			int lerpIndex = 0;
			
			int ovv, vv;
			
			//PMM -- added RF_SHELL_DOUBLE, RF_SHELL_HALF_DAM
			if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0)
			{
				float[] normal;
				for (i = 0; i < nverts; i++)
				{
					vv = v[i];
					normal = r_avertexnormals[(SupportClass.URShift(vv, 24)) & 0xFF];
					ovv = ov[i];
					
					lerp[i][0] = move[0] + (ovv & 0xFF) * backv[0] + (vv & 0xFF) * frontv[0] + normal[0] * Defines.POWERSUIT_SCALE;
					lerp[i][1] = move[1] + ((SupportClass.URShift(ovv, 8)) & 0xFF) * backv[1] + ((SupportClass.URShift(vv, 8)) & 0xFF) * frontv[1] + normal[1] * Defines.POWERSUIT_SCALE;
					lerp[i][2] = move[2] + ((SupportClass.URShift(ovv, 16)) & 0xFF) * backv[2] + ((SupportClass.URShift(vv, 16)) & 0xFF) * frontv[2] + normal[2] * Defines.POWERSUIT_SCALE;
				}
			}
			else
			{
				for (i = 0; i < nverts; i++)
				{
					vv = v[i];
					ovv = ov[i];
					lerp[i][0] = move[0] + (ovv & 0xFF) * backv[0] + (vv & 0xFF) * frontv[0];
					lerp[i][1] = move[1] + ((SupportClass.URShift(ovv, 8)) & 0xFF) * backv[1] + ((SupportClass.URShift(vv, 8)) & 0xFF) * frontv[1];
					lerp[i][2] = move[2] + ((SupportClass.URShift(ovv, 16)) & 0xFF) * backv[2] + ((SupportClass.URShift(vv, 16)) & 0xFF) * frontv[2];
				}
			}
		}
		
		internal virtual void  GL_LerpVerts(int nverts, int[] ov, int[] v, float[] move, float[] frontv, float[] backv)
		{
			int lerpIndex = 0;
			
			int ovv, vv;
			FloatBuffer lerp = vertexArrayBuf;
			
			//PMM -- added RF_SHELL_DOUBLE, RF_SHELL_HALF_DAM
			if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0)
			{
				float[] normal;
				int j = 0;
				for (int i = 0; i < nverts; i++)
				{
					vv = v[i];
					normal = r_avertexnormals[(SupportClass.URShift(v[i], 24)) & 0xFF];
					ovv = ov[i];
					
					lerp.put(j, move[0] + (ovv & 0xFF) * backv[0] + (vv & 0xFF) * frontv[0] + normal[0] * Defines.POWERSUIT_SCALE);
					lerp.put(j + 1, move[1] + ((SupportClass.URShift(ovv, 8)) & 0xFF) * backv[1] + ((SupportClass.URShift(vv, 8)) & 0xFF) * frontv[1] + normal[1] * Defines.POWERSUIT_SCALE);
					lerp.put(j + 2, move[2] + ((SupportClass.URShift(ovv, 16)) & 0xFF) * backv[2] + ((SupportClass.URShift(vv, 16)) & 0xFF) * frontv[2] + normal[2] * Defines.POWERSUIT_SCALE);
					j += 3;
				}
			}
			else
			{
				int j = 0;
				for (int i = 0; i < nverts; i++)
				{
					ovv = ov[i];
					vv = v[i];
					
					lerp.put(j, move[0] + (ovv & 0xFF) * backv[0] + (vv & 0xFF) * frontv[0]);
					lerp.put(j + 1, move[1] + ((SupportClass.URShift(ovv, 8)) & 0xFF) * backv[1] + ((SupportClass.URShift(vv, 8)) & 0xFF) * frontv[1]);
					lerp.put(j + 2, move[2] + ((SupportClass.URShift(ovv, 16)) & 0xFF) * backv[2] + ((SupportClass.URShift(vv, 16)) & 0xFF) * frontv[2]);
					j += 3;
				}
			}
		}
		
		//UPGRADE_NOTE: The initialization of  'colorArrayBuf' was moved to method 'InitBlock'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal FloatBuffer colorArrayBuf;
		
		//UPGRADE_NOTE: The initialization of  'vertexArrayBuf' was moved to method 'InitBlock'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal FloatBuffer vertexArrayBuf;
		
		internal bool isFilled = false;
		
		internal float[] tmpVec = new float[]{0, 0, 0};
		
		/*
		* ============= GL_DrawAliasFrameLerp
		* 
		* interpolates between two frames and origins FIXME: batch lerp all
		* vertexes =============
		*/
		internal virtual void  GL_DrawAliasFrameLerp(qfiles.dmdl_t paliashdr, float backlerp)
		{
			float l;
			qfiles.daliasframe_t frame, oldframe;
			int[] v, ov;
			
			int[] order;
			int orderIndex = 0;
			int count;
			
			float frontlerp;
			float alpha;
			
			float[] move = new float[]{0, 0, 0}; // vec3_t
			float[][] vectors = new float[][]{new float[]{0, 0, 0}, new float[]{0, 0, 0}, new float[]{0, 0, 0}};
			
			float[] frontv = new float[]{0, 0, 0}; // vec3_t
			float[] backv = new float[]{0, 0, 0}; // vec3_t
			
			int i;
			int index_xyz;
			//float[][] lerp;
			
			frame = paliashdr.aliasFrames[currententity.frame];
			
			v = frame.verts;
			
			oldframe = paliashdr.aliasFrames[currententity.oldframe];
			
			ov = oldframe.verts;
			
			order = paliashdr.glCmds;
			
			if ((currententity.flags & Defines.RF_TRANSLUCENT) != 0)
				alpha = currententity.alpha;
			else
				alpha = 1.0f;
			
			// PMM - added double shell
			if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0)
				gl.glDisable(net.java.games.jogl.GL_Fields.GL_TEXTURE_2D);
			
			frontlerp = 1.0f - backlerp;
			
			// move should be the delta back to the previous frame * backlerp
			Math3D.VectorSubtract(currententity.oldorigin, currententity.origin, frontv);
			Math3D.AngleVectors(currententity.angles, vectors[0], vectors[1], vectors[2]);
			
			move[0] = Math3D.DotProduct(frontv, vectors[0]); // forward
			move[1] = - Math3D.DotProduct(frontv, vectors[1]); // left
			move[2] = Math3D.DotProduct(frontv, vectors[2]); // up
			
			Math3D.VectorAdd(move, oldframe.translate, move);
			
			for (i = 0; i < 3; i++)
			{
				move[i] = backlerp * move[i] + frontlerp * frame.translate[i];
				frontv[i] = frontlerp * frame.scale[i];
				backv[i] = backlerp * oldframe.scale[i];
			}
			
			if (gl_vertex_arrays.value_Renamed != 0.0f)
			{
				GL_LerpVerts(paliashdr.num_xyz, ov, v, move, frontv, backv);
				
				gl.glEnableClientState(net.java.games.jogl.GL_Fields.GL_VERTEX_ARRAY);
				gl.glVertexPointer(3, net.java.games.jogl.GL_Fields.GL_FLOAT, 0, vertexArrayBuf);
				
				// PMM - added double damage shell
				if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0)
				{
					
					gl.glDisableClientState(net.java.games.jogl.GL_Fields.GL_COLOR_ARRAY);
					gl.glColor4f(shadelight[0], shadelight[1], shadelight[2], alpha);
				}
				else
				{
					gl.glEnableClientState(net.java.games.jogl.GL_Fields.GL_COLOR_ARRAY);
					gl.glColorPointer(4, net.java.games.jogl.GL_Fields.GL_FLOAT, 0, colorArrayBuf);
					
					//
					// pre light everything
					//
					FloatBuffer color = colorArrayBuf;
					int j = 0;
					for (i = 0; i < paliashdr.num_xyz; i++)
					{
						// light normal index
						l = shadedots[(SupportClass.URShift(v[i], 24)) & 0xFF];
						color.put(j++, l * shadelight[0]);
						color.put(j++, l * shadelight[1]);
						color.put(j++, l * shadelight[2]);
						color.put(j++, alpha);
					}
				}
				
				if (qglLockArraysEXT)
					gl.glLockArraysEXT(0, paliashdr.num_xyz);
				
				while (true)
				{
					// get the vertex count and primitive type
					count = order[orderIndex++];
					if (count == 0)
						break; // done
					if (count < 0)
					{
						count = - count;
						gl.glBegin(net.java.games.jogl.GL_Fields.GL_TRIANGLE_FAN);
					}
					else
					{
						gl.glBegin(net.java.games.jogl.GL_Fields.GL_TRIANGLE_STRIP);
					}
					
					// PMM - added double damage shell
					if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0)
					{
						do 
						{
							index_xyz = order[orderIndex + 2];
							orderIndex += 3;
							/*
							* vertexArrayBuf.position(4 * index_xyz);
							* vertexArrayBuf.get(tmpVec); gl.glVertex3fv( tmpVec );
							*/
							gl.glArrayElement(index_xyz);
						}
						while (--count != 0);
					}
					else
					{
						do 
						{
							// texture coordinates come from the draw list
							//UPGRADE_ISSUE: Method 'java.lang.Float.intBitsToFloat' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javalangFloatintBitsToFloat_int'"
							gl.glTexCoord2f(Float.intBitsToFloat(order[orderIndex + 0]), Float.intBitsToFloat(order[orderIndex + 1]));
							
							index_xyz = order[orderIndex + 2];
							orderIndex += 3;
							
							// normals and vertexes come from the frame list
							gl.glArrayElement(index_xyz);
						}
						while (--count != 0);
					}
					gl.glEnd();
				}
				
				if (qglLockArraysEXT)
					gl.glUnlockArraysEXT();
			}
			else
			{
				GL_LerpVerts(paliashdr.num_xyz, ov, v, s_lerped, move, frontv, backv);
				
				float[] tmp;
				
				while (true)
				{
					// get the vertex count and primitive type
					count = order[orderIndex++];
					if (count == 0)
						break; // done
					if (count < 0)
					{
						count = - count;
						gl.glBegin(net.java.games.jogl.GL_Fields.GL_TRIANGLE_FAN);
					}
					else
					{
						gl.glBegin(net.java.games.jogl.GL_Fields.GL_TRIANGLE_STRIP);
					}
					
					if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE)) != 0)
					{
						do 
						{
							index_xyz = order[orderIndex + 2];
							orderIndex += 3;
							
							gl.glColor4f(shadelight[0], shadelight[1], shadelight[2], alpha);
							tmp = s_lerped[index_xyz];
							gl.glVertex3f(tmp[0], tmp[1], tmp[2]);
						}
						while (--count != 0);
					}
					else
					{
						do 
						{
							// texture coordinates come from the draw list
							// gl.glTexCoord2f (((float *)order)[0], ((float
							// *)order)[1]);
							
							//UPGRADE_ISSUE: Method 'java.lang.Float.intBitsToFloat' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javalangFloatintBitsToFloat_int'"
							gl.glTexCoord2f(Float.intBitsToFloat(order[orderIndex + 0]), Float.intBitsToFloat(order[orderIndex + 1]));
							index_xyz = order[orderIndex + 2];
							orderIndex += 3;
							
							// normals and vertexes come from the frame list
							l = shadedots[(SupportClass.URShift(v[index_xyz], 24)) & 0xFF];
							
							gl.glColor4f(l * shadelight[0], l * shadelight[1], l * shadelight[2], alpha);
							tmp = s_lerped[index_xyz];
							gl.glVertex3f(tmp[0], tmp[1], tmp[2]);
						}
						while (--count != 0);
					}
					gl.glEnd();
				}
			}
			
			// PMM - added double damage shell
			if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0)
				gl.glEnable(net.java.games.jogl.GL_Fields.GL_TEXTURE_2D);
		}
		
		/*
		* ============= GL_DrawAliasShadow =============
		*/
		internal virtual void  GL_DrawAliasShadow(qfiles.dmdl_t paliashdr, int posenum)
		{
			float[] point = new float[]{0, 0, 0};
			int count;
			qfiles.daliasframe_t frame;
			
			float lheight = currententity.origin[2] - lightspot[2];
			
			frame = paliashdr.aliasFrames[currententity.frame];
			
			int[] order = paliashdr.glCmds;
			
			float height = - lheight + 1.0f;
			
			int orderIndex = 0;
			int index = 0;
			
			while (true)
			{
				// get the vertex count and primitive type
				count = order[orderIndex++];
				if (count == 0)
					break; // done
				if (count < 0)
				{
					count = - count;
					gl.glBegin(net.java.games.jogl.GL_Fields.GL_TRIANGLE_FAN);
				}
				else
					gl.glBegin(net.java.games.jogl.GL_Fields.GL_TRIANGLE_STRIP);
				
				do 
				{
					// normals and vertexes come from the frame list
					/*
					* point[0] = verts[order[2]].v[0] * frame.scale[0] +
					* frame.translate[0]; point[1] = verts[order[2]].v[1] *
					* frame.scale[1] + frame.translate[1]; point[2] =
					* verts[order[2]].v[2] * frame.scale[2] + frame.translate[2];
					*/
					
					if (gl_vertex_arrays.value_Renamed != 0.0f)
					{
						index = order[orderIndex + 2] * 3;
						point[0] = vertexArrayBuf.get_Renamed(index);
						point[1] = vertexArrayBuf.get_Renamed(index + 1);
						point[2] = vertexArrayBuf.get_Renamed(index + 2);
					}
					else
					{
						Math3D.VectorCopy(s_lerped[order[orderIndex + 2]], point);
					}
					
					point[0] -= shadevector[0] * (point[2] + lheight);
					point[1] -= shadevector[1] * (point[2] + lheight);
					point[2] = height;
					gl.glVertex3f(point[0], point[1], point[2]);
					
					orderIndex += 3;
				}
				while (--count != 0);
				
				gl.glEnd();
			}
		}
		
		/*
		* * R_CullAliasModel
		*/
		internal virtual bool R_CullAliasModel(float[][] bbox, entity_t e)
		{
			int i;
			float[] mins = new float[]{0, 0, 0};
			float[] maxs = new float[]{0, 0, 0};
			
			qfiles.dmdl_t paliashdr;
			
			float[][] vectors = new float[][]{new float[]{0, 0, 0}, new float[]{0, 0, 0}, new float[]{0, 0, 0}};
			
			float[] thismins = new float[]{0, 0, 0};
			float[] oldmins = new float[]{0, 0, 0};
			float[] thismaxs = new float[]{0, 0, 0};
			float[] oldmaxs = new float[]{0, 0, 0};
			qfiles.daliasframe_t pframe, poldframe;
			float[] angles = new float[]{0, 0, 0};
			
			paliashdr = (qfiles.dmdl_t) currentmodel.extradata;
			
			if ((e.frame >= paliashdr.num_frames) || (e.frame < 0))
			{
				VID.Printf(Defines.PRINT_ALL, "R_CullAliasModel " + currentmodel.name + ": no such frame " + e.frame + '\n');
				e.frame = 0;
			}
			if ((e.oldframe >= paliashdr.num_frames) || (e.oldframe < 0))
			{
				VID.Printf(Defines.PRINT_ALL, "R_CullAliasModel " + currentmodel.name + ": no such oldframe " + e.oldframe + '\n');
				e.oldframe = 0;
			}
			
			pframe = paliashdr.aliasFrames[e.frame];
			poldframe = paliashdr.aliasFrames[e.oldframe];
			
			/*
			* * compute axially aligned mins and maxs
			*/
			if (pframe == poldframe)
			{
				for (i = 0; i < 3; i++)
				{
					mins[i] = pframe.translate[i];
					maxs[i] = mins[i] + pframe.scale[i] * 255;
				}
			}
			else
			{
				for (i = 0; i < 3; i++)
				{
					thismins[i] = pframe.translate[i];
					thismaxs[i] = thismins[i] + pframe.scale[i] * 255;
					
					oldmins[i] = poldframe.translate[i];
					oldmaxs[i] = oldmins[i] + poldframe.scale[i] * 255;
					
					if (thismins[i] < oldmins[i])
						mins[i] = thismins[i];
					else
						mins[i] = oldmins[i];
					
					if (thismaxs[i] > oldmaxs[i])
						maxs[i] = thismaxs[i];
					else
						maxs[i] = oldmaxs[i];
				}
			}
			
			/*
			* * compute a full bounding box
			*/
			for (i = 0; i < 8; i++)
			{
				float[] tmp = new float[]{0, 0, 0};
				
				if ((i & 1) != 0)
					tmp[0] = mins[0];
				else
					tmp[0] = maxs[0];
				
				if ((i & 2) != 0)
					tmp[1] = mins[1];
				else
					tmp[1] = maxs[1];
				
				if ((i & 4) != 0)
					tmp[2] = mins[2];
				else
					tmp[2] = maxs[2];
				
				Math3D.VectorCopy(tmp, bbox[i]);
			}
			
			/*
			* * rotate the bounding box
			*/
			Math3D.VectorCopy(e.angles, angles);
			angles[YAW] = - angles[YAW];
			Math3D.AngleVectors(angles, vectors[0], vectors[1], vectors[2]);
			
			for (i = 0; i < 8; i++)
			{
				float[] tmp = new float[]{0, 0, 0};
				
				Math3D.VectorCopy(bbox[i], tmp);
				
				bbox[i][0] = Math3D.DotProduct(vectors[0], tmp);
				bbox[i][1] = - Math3D.DotProduct(vectors[1], tmp);
				bbox[i][2] = Math3D.DotProduct(vectors[2], tmp);
				
				Math3D.VectorAdd(e.origin, bbox[i], bbox[i]);
			}
			
			{
				int p, f;
				int aggregatemask = ~ 0; // 0xFFFFFFFF
				
				for (p = 0; p < 8; p++)
				{
					int mask = 0;
					
					for (f = 0; f < 4; f++)
					{
						float dp = Math3D.DotProduct(frustum[f].normal, bbox[p]);
						
						if ((dp - frustum[f].dist) < 0)
						{
							mask |= (1 << f);
						}
					}
					
					aggregatemask &= mask;
				}
				
				if (aggregatemask != 0)
				{
					return true;
				}
				
				return false;
			}
		}
		
		/*
		* ================= R_DrawAliasModel
		* 
		* =================
		*/
		internal override void  R_DrawAliasModel(entity_t e)
		{
			int i;
			qfiles.dmdl_t paliashdr;
			float an;
			
			// bounding box
			float[][] bbox = new float[][]{new float[]{0, 0, 0}, new float[]{0, 0, 0}, new float[]{0, 0, 0}, new float[]{0, 0, 0}, new float[]{0, 0, 0}, new float[]{0, 0, 0}, new float[]{0, 0, 0}, new float[]{0, 0, 0}};
			image_t skin;
			
			if ((e.flags & Defines.RF_WEAPONMODEL) == 0)
			{
				if (R_CullAliasModel(bbox, e))
					return ;
			}
			
			if ((e.flags & Defines.RF_WEAPONMODEL) != 0)
			{
				if (r_lefthand.value_Renamed == 2.0f)
					return ;
			}
			
			paliashdr = (qfiles.dmdl_t) currentmodel.extradata;
			
			//
			// get lighting information
			//
			// PMM - rewrote, reordered to handle new shells & mixing
			// PMM - 3.20 code .. replaced with original way of doing it to keep mod
			// authors happy
			//
			if ((currententity.flags & (Defines.RF_SHELL_HALF_DAM | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_RED | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE)) != 0)
			{
				Math3D.VectorClear(shadelight);
				if ((currententity.flags & Defines.RF_SHELL_HALF_DAM) != 0)
				{
					shadelight[0] = 0.56f;
					shadelight[1] = 0.59f;
					shadelight[2] = 0.45f;
				}
				if ((currententity.flags & Defines.RF_SHELL_DOUBLE) != 0)
				{
					shadelight[0] = 0.9f;
					shadelight[1] = 0.7f;
				}
				if ((currententity.flags & Defines.RF_SHELL_RED) != 0)
					shadelight[0] = 1.0f;
				if ((currententity.flags & Defines.RF_SHELL_GREEN) != 0)
					shadelight[1] = 1.0f;
				if ((currententity.flags & Defines.RF_SHELL_BLUE) != 0)
					shadelight[2] = 1.0f;
			}
			else if ((currententity.flags & Defines.RF_FULLBRIGHT) != 0)
			{
				for (i = 0; i < 3; i++)
					shadelight[i] = 1.0f;
			}
			else
			{
				R_LightPoint(currententity.origin, shadelight);
				
				// player lighting hack for communication back to server
				// big hack!
				if ((currententity.flags & Defines.RF_WEAPONMODEL) != 0)
				{
					// pick the greatest component, which should be the same
					// as the mono value returned by software
					if (shadelight[0] > shadelight[1])
					{
						if (shadelight[0] > shadelight[2])
							r_lightlevel.value_Renamed = 150 * shadelight[0];
						else
							r_lightlevel.value_Renamed = 150 * shadelight[2];
					}
					else
					{
						if (shadelight[1] > shadelight[2])
							r_lightlevel.value_Renamed = 150 * shadelight[1];
						else
							r_lightlevel.value_Renamed = 150 * shadelight[2];
					}
				}
				
				if (gl_monolightmap.string_Renamed[0] != '0')
				{
					float s = shadelight[0];
					
					if (s < shadelight[1])
						s = shadelight[1];
					if (s < shadelight[2])
						s = shadelight[2];
					
					shadelight[0] = s;
					shadelight[1] = s;
					shadelight[2] = s;
				}
			}
			
			if ((currententity.flags & Defines.RF_MINLIGHT) != 0)
			{
				for (i = 0; i < 3; i++)
					if (shadelight[i] > 0.1f)
						break;
				if (i == 3)
				{
					shadelight[0] = 0.1f;
					shadelight[1] = 0.1f;
					shadelight[2] = 0.1f;
				}
			}
			
			if ((currententity.flags & Defines.RF_GLOW) != 0)
			{
				// bonus items will
				// pulse with time
				float scale;
				float min;
				
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				scale = (float) (0.1f * System.Math.Sin(r_newrefdef.time * 7));
				for (i = 0; i < 3; i++)
				{
					min = shadelight[i] * 0.8f;
					shadelight[i] += scale;
					if (shadelight[i] < min)
						shadelight[i] = min;
				}
			}
			
			// =================
			// PGM ir goggles color override
			if ((r_newrefdef.rdflags & Defines.RDF_IRGOGGLES) != 0 && (currententity.flags & Defines.RF_IR_VISIBLE) != 0)
			{
				shadelight[0] = 1.0f;
				shadelight[1] = 0.0f;
				shadelight[2] = 0.0f;
			}
			// PGM
			// =================
			
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			shadedots = r_avertexnormal_dots[((int) (currententity.angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
			
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			an = (float) (currententity.angles[1] / 180 * System.Math.PI);
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			shadevector[0] = (float) System.Math.Cos(- an);
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			shadevector[1] = (float) System.Math.Sin(- an);
			shadevector[2] = 1;
			Math3D.VectorNormalize(shadevector);
			
			//
			// locate the proper data
			//
			
			c_alias_polys += paliashdr.num_tris;
			
			//
			// draw all the triangles
			//
			if ((currententity.flags & Defines.RF_DEPTHHACK) != 0)
			// hack the depth range to prevent view model from poking into walls
				gl.glDepthRange(gldepthmin, gldepthmin + 0.3 * (gldepthmax - gldepthmin));
			
			if ((currententity.flags & Defines.RF_WEAPONMODEL) != 0 && (r_lefthand.value_Renamed == 1.0f))
			{
				gl.glMatrixMode(net.java.games.jogl.GL_Fields.GL_PROJECTION);
				gl.glPushMatrix();
				gl.glLoadIdentity();
				gl.glScalef(- 1, 1, 1);
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				MYgluPerspective(r_newrefdef.fov_y, (float) r_newrefdef.width / r_newrefdef.height, 4, 4096);
				gl.glMatrixMode(net.java.games.jogl.GL_Fields.GL_MODELVIEW);
				
				gl.glCullFace(net.java.games.jogl.GL_Fields.GL_BACK);
			}
			
			gl.glPushMatrix();
			e.angles[PITCH] = - e.angles[PITCH]; // sigh.
			R_RotateForEntity(e);
			e.angles[PITCH] = - e.angles[PITCH]; // sigh.
			
			// select skin
			if (currententity.skin != null)
				skin = currententity.skin;
			// custom player skin
			else
			{
				if (currententity.skinnum >= qfiles.MAX_MD2SKINS)
					skin = currentmodel.skins[0];
				else
				{
					skin = currentmodel.skins[currententity.skinnum];
					if (skin == null)
						skin = currentmodel.skins[0];
				}
			}
			if (skin == null)
				skin = r_notexture; // fallback...
			GL_Bind(skin.texnum);
			
			// draw it
			
			gl.glShadeModel(net.java.games.jogl.GL_Fields.GL_SMOOTH);
			
			GL_TexEnv(net.java.games.jogl.GL_Fields.GL_MODULATE);
			if ((currententity.flags & Defines.RF_TRANSLUCENT) != 0)
			{
				gl.glEnable(net.java.games.jogl.GL_Fields.GL_BLEND);
			}
			
			if ((currententity.frame >= paliashdr.num_frames) || (currententity.frame < 0))
			{
				VID.Printf(Defines.PRINT_ALL, "R_DrawAliasModel " + currentmodel.name + ": no such frame " + currententity.frame + '\n');
				currententity.frame = 0;
				currententity.oldframe = 0;
			}
			
			if ((currententity.oldframe >= paliashdr.num_frames) || (currententity.oldframe < 0))
			{
				VID.Printf(Defines.PRINT_ALL, "R_DrawAliasModel " + currentmodel.name + ": no such oldframe " + currententity.oldframe + '\n');
				currententity.frame = 0;
				currententity.oldframe = 0;
			}
			
			if (r_lerpmodels.value_Renamed == 0.0f)
				currententity.backlerp = 0;
			GL_DrawAliasFrameLerp(paliashdr, currententity.backlerp);
			
			GL_TexEnv(net.java.games.jogl.GL_Fields.GL_REPLACE);
			gl.glShadeModel(net.java.games.jogl.GL_Fields.GL_FLAT);
			
			gl.glPopMatrix();
			
			if ((currententity.flags & Defines.RF_WEAPONMODEL) != 0 && (r_lefthand.value_Renamed == 1.0F))
			{
				gl.glMatrixMode(net.java.games.jogl.GL_Fields.GL_PROJECTION);
				gl.glPopMatrix();
				gl.glMatrixMode(net.java.games.jogl.GL_Fields.GL_MODELVIEW);
				gl.glCullFace(net.java.games.jogl.GL_Fields.GL_FRONT);
			}
			
			if ((currententity.flags & Defines.RF_TRANSLUCENT) != 0)
			{
				gl.glDisable(net.java.games.jogl.GL_Fields.GL_BLEND);
			}
			
			if ((currententity.flags & Defines.RF_DEPTHHACK) != 0)
				gl.glDepthRange(gldepthmin, gldepthmax);
			
			if (gl_shadows.value_Renamed != 0.0f && (currententity.flags & (Defines.RF_TRANSLUCENT | Defines.RF_WEAPONMODEL)) == 0)
			{
				gl.glPushMatrix();
				R_RotateForEntity(e);
				gl.glDisable(net.java.games.jogl.GL_Fields.GL_TEXTURE_2D);
				gl.glEnable(net.java.games.jogl.GL_Fields.GL_BLEND);
				gl.glColor4f(0, 0, 0, 0.5f);
				GL_DrawAliasShadow(paliashdr, currententity.frame);
				gl.glEnable(net.java.games.jogl.GL_Fields.GL_TEXTURE_2D);
				gl.glDisable(net.java.games.jogl.GL_Fields.GL_BLEND);
				gl.glPopMatrix();
			}
			gl.glColor4f(1, 1, 1, 1);
		}
	}
}